#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "vecinos.h"

/**
  \struct Estructura "neighbours" o vecinos.
  list : Una glist de vecinos.
  current : ultima posicion que se utilizo en la lista, simulando una cinta.
*/
struct s_neighbours{
    GList *list; /*!< Lista de vecinos*/
    int current; /*!< El vecino actual de la lista*/
};


/**
  Creador de vecinos.
  \return  : Una nueva lista de vecinos vacia.
*/
neighbours neighbours_create(void){
    neighbours nbor = NULL;
    nbor = (neighbours) malloc(sizeof(struct s_neighbours));
    if (nbor == NULL){
        printf("Memoria insuficiente\n");
        exit(1);
    }
    nbor->list = NULL;
    nbor->current = 0;
    return nbor;
}

/**
  Agrega un vecino a la lista actual de vecinos.
  \pre
    <code> (nbor != NULL && edg != NULL) </code>
  \param nbor : La lista actual de vecinos.
  \param edg : el nuevo vecino a ser agregado.
  \return  : void
*/
void neighbour_add(neighbours nbor, edge edg){
    assert(nbor!=NULL && edg!=NULL);
    nbor-> list  = g_list_insert(nbor-> list, edg, nbor-> current);
    nbor-> current++;
}

/**
 * Verifica si existe algun vecino en la lista actual de vecinos.
 * \pre
    <code> (nbor != NULL) </code>
 * \param nbor : La lista actual de vecinos.
 * \return  : True si la lista si no hay vecinos, Falso c.c.
 */
bool neighbours_empty(neighbours nbor){
    assert(nbor!=NULL);
    return g_list_length(nbor-> list) == 0;
}

/**
  Avanza al proximo vecino.
   \pre
    <code> (nbor != NULL) </code>
  \param nbor : La lista actual de vecinos.
  \return  : void
*/
void neighbours_next(neighbours nbor){
    int size = g_list_length(nbor-> list);
    nbor-> current = (nbor-> current + 1) % size;
}

/**
  Vecino sobre el que estamos parados.
  * \pre
    <code> (nbor != NULL) </code>
  \param nbor : La lista actual de vecinos.
  \return  : El vecino actual sobre el cual esta parada la cinta.
*/
edge neighbours_current(neighbours nbor){
    assert(nbor!=NULL);
    return (edge) g_list_nth_data(nbor-> list, nbor-> current-1);
}

/**
  Cantidad de vecinos.
   \pre
    <code> (nbor != NULL) </code>
  \param nbor : La lista actual de vecinos.
  \return  : Cantidad de vecinos
*/
int neighbours_size(neighbours nbor){
    assert(nbor!=NULL);
    return g_list_length(nbor-> list);
}

/**
  Destructor de vecinos.
   \pre
    <code> (nbor != NULL) </code>
  \param nbor : La lista actual de vecinos.
  \return  : NULL.
 */
neighbours neighbours_destroy(neighbours nbor){
    assert(nbor!=NULL);
    g_list_free(nbor-> list);
    free(nbor);
    return NULL;
}

